#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
视觉分析结果解析器模块
负责将智谱视觉API返回的结果转换为系统标准格式

T2-04子任务：视觉分析结果解析器
输入：API返回结果
输出：结构化的分析结果
"""

import json
import re
from typing import Dict, Any, List, Optional, Tuple
from datetime import datetime
import logging

# 配置日志
logger = logging.getLogger(__name__)


class VisionResultParser:
    """
    视觉分析结果解析器
    将智谱视觉API返回的原始结果解析为系统标准格式
    """
    
    def __init__(self):
        """
        初始化视觉分析结果解析器
        """
        # 预定义的分析类目
        self.supported_categories = {
            "scene_setting": "场景设定",
            "audio_material": "声音素材",
            "theme_type": "主题类型",
            "emotional_tendency": "视频情感倾向",
            "topic_tags": "话题标签",
            "author_nickname_type": "作者昵称类型",
            "author_intro_content": "作者简介内容"
        }
        
        # 结果结构模板
        self.result_template = {
            "status": "success",
            "video_id": "",
            "analysis_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "overall_confidence": 0,
            "encoding_categories": {},
            "raw_content": None,
            "error_message": None,
            "fields_to_supplement": []
        }
    
    def parse_result(self, api_result: Dict[str, Any], video_id: str = "") -> Dict[str, Any]:
        """
        解析API返回的结果
        
        Args:
            api_result: API调用结果字典
            video_id: 视频ID
            
        Returns:
            Dict[str, Any]: 标准化的分析结果
        """
        # 初始化结果
        result = self.result_template.copy()
        result["video_id"] = video_id
        
        # 检查API调用是否成功
        if not api_result.get("success", False):
            result["status"] = "error"
            result["error_message"] = api_result.get("error", "API调用失败")
            logger.error(f"API调用失败: {result['error_message']}")
            return result
        
        # 获取原始内容
        content = api_result.get("content", "")
        result["raw_content"] = content
        
        try:
            # 尝试解析不同格式的响应
            parsed_data = self._extract_data(content)
            
            if not parsed_data:
                raise ValueError("无法从响应中提取有效数据")
            
            # 转换为标准格式
            standard_result = self._convert_to_standard_format(parsed_data, video_id)
            
            # 合并结果
            result.update(standard_result)
            
            # 计算需要补充的字段
            result["fields_to_supplement"] = self._identify_fields_to_supplement(result)
            
            logger.info(f"视觉分析结果解析成功，视频ID: {video_id}")
            return result
            
        except Exception as e:
            result["status"] = "error"
            result["error_message"] = f"解析失败: {str(e)}"
            logger.error(f"解析API响应失败: {str(e)}")
            return result
    
    def _extract_data(self, content: str) -> Dict[str, Any]:
        """
        从响应内容中提取数据
        支持多种格式：JSON标记块、纯JSON、文本提取等
        
        Args:
            content: API返回的原始内容
            
        Returns:
            Dict[str, Any]: 提取的数据字典
        """
        # 方法1: 查找 JSON 标记块
        json_match = re.search(r'```json\s*(.*?)\s*```', content, re.DOTALL)
        if json_match:
            try:
                return json.loads(json_match.group(1))
            except json.JSONDecodeError:
                logger.warning("JSON标记块解析失败，尝试其他方法")
        
        # 方法2: 尝试直接解析整个内容为JSON
        try:
            return json.loads(content)
        except json.JSONDecodeError:
            logger.warning("直接JSON解析失败，尝试文本提取")
        
        # 方法3: 文本模式提取 - 尝试从文本中提取结构化信息
        extracted_data = self._extract_from_text(content)
        if extracted_data:
            return extracted_data
        
        # 方法4: 查找键值对模式
        kv_data = self._extract_key_value_pairs(content)
        if kv_data:
            return kv_data
        
        raise ValueError("无法从响应中提取有效数据")
    
    def _extract_from_text(self, content: str) -> Dict[str, Any]:
        """
        从纯文本中提取分析结果
        
        Args:
            content: 文本内容
            
        Returns:
            Dict[str, Any]: 提取的数据
        """
        result = {}
        
        # 针对每个预定义的类目进行文本提取
        for category_key, category_name in self.supported_categories.items():
            # 构建正则表达式查找模式
            # 例如: 场景设定：校园场景 (置信度: 85%)
            pattern = rf'{re.escape(category_name)}[:：]\s*(.+?)\s*(?:\(置信度[:：]\s*(\d+)%\))?'
            match = re.search(pattern, content, re.IGNORECASE)
            
            if match:
                option = match.group(1).strip()
                confidence = int(match.group(2)) if match.group(2) else 70  # 默认置信度
                
                result[category_key] = {
                    "option": option,
                    "confidence": confidence,
                    "source": "text_extraction"
                }
        
        # 如果提取到了至少一个类目，返回结果
        if result:
            return result
        
        return None
    
    def _extract_key_value_pairs(self, content: str) -> Dict[str, Any]:
        """
        从键值对格式文本中提取数据
        
        Args:
            content: 文本内容
            
        Returns:
            Dict[str, Any]: 提取的数据
        """
        result = {}
        
        # 尝试提取键值对
        lines = content.strip().split('\n')
        for line in lines:
            line = line.strip()
            if ':' in line or '：' in line:
                # 查找第一个冒号作为分隔符
                separator_index = line.find(':') if ':' in line else line.find('：')
                if separator_index > 0:
                    key = line[:separator_index].strip().lower()
                    value = line[separator_index + 1:].strip()
                    
                    # 检查是否是已知的类目
                    for category_key, category_name in self.supported_categories.items():
                        if category_name.lower() in key or category_key in key:
                            # 尝试提取置信度
                            confidence_match = re.search(r'(\d+)%', value)
                            confidence = int(confidence_match.group(1)) if confidence_match else 60
                            option = re.sub(r'\(.*?\)', '', value).strip()
                            
                            result[category_key] = {
                                "option": option,
                                "confidence": confidence,
                                "source": "key_value_extraction"
                            }
                            break
        
        return result if result else None
    
    def _convert_to_standard_format(self, parsed_data: Dict[str, Any], video_id: str) -> Dict[str, Any]:
        """
        将解析的数据转换为系统标准格式
        
        Args:
            parsed_data: 解析后的数据
            video_id: 视频ID
            
        Returns:
            Dict[str, Any]: 标准化的结果
        """
        standard_result = {
            "video_id": video_id,
            "analysis_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "encoding_categories": {},
            "overall_confidence": 0
        }
        
        # 收集所有置信度值，用于计算总体置信度
        confidences = []
        
        # 处理各个类目
        for category_key, category_name in self.supported_categories.items():
            if category_key in parsed_data:
                category_data = parsed_data[category_key]
                
                # 处理嵌套的类目数据格式
                if isinstance(category_data, dict):
                    option = category_data.get("option", category_data.get("value", "未知"))
                    confidence = category_data.get("confidence", 60)
                    source = category_data.get("source", "api_response")
                else:
                    # 如果是简单值，作为选项
                    option = str(category_data)
                    confidence = 60  # 默认置信度
                    source = "simple_value"
                
                # 标准化类目数据
                standard_result["encoding_categories"][category_key] = {
                    "name": category_name,
                    "option": option,
                    "confidence": confidence,
                    "source": source,
                    "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                }
                
                confidences.append(confidence)
        
        # 计算总体置信度
        if confidences:
            standard_result["overall_confidence"] = int(sum(confidences) / len(confidences))
        
        # 复制其他可能的字段
        for key, value in parsed_data.items():
            if key not in standard_result and key not in self.supported_categories:
                standard_result[key] = value
        
        return standard_result
    
    def _identify_fields_to_supplement(self, result: Dict[str, Any]) -> List[str]:
        """
        识别需要补充推断的字段
        
        Args:
            result: 分析结果
            
        Returns:
            List[str]: 需要补充的字段列表
        """
        fields_to_supplement = []
        encoding_categories = result.get("encoding_categories", {})
        
        # 低置信度阈值
        low_confidence_threshold = 70
        
        for category_key, category_data in encoding_categories.items():
            confidence = category_data.get("confidence", 0)
            option = category_data.get("option", "")
            
            # 需要补充的条件：
            # 1. 置信度低于阈值
            # 2. 选项为空或包含"未知"、"其他"等
            if (confidence < low_confidence_threshold or 
                not option or 
                any(keyword in option for keyword in ["未知", "其他", "未分类", "无法确定"])):
                fields_to_supplement.append(category_key)
        
        # 如果某些重要类目缺失，也添加到补充列表
        important_categories = ["scene_setting", "theme_type", "emotional_tendency"]
        for category_key in important_categories:
            if category_key not in encoding_categories and category_key not in fields_to_supplement:
                fields_to_supplement.append(category_key)
        
        return fields_to_supplement
    
    def validate_result(self, result: Dict[str, Any]) -> Tuple[bool, List[str]]:
        """
        验证解析结果的完整性和有效性
        
        Args:
            result: 解析后的结果
            
        Returns:
            Tuple[bool, List[str]]: (验证是否通过, 错误信息列表)
        """
        errors = []
        
        # 检查基本字段
        if result.get("status") == "error":
            errors.append(f"解析错误: {result.get('error_message', '未知错误')}")
            return False, errors
        
        # 检查是否有至少一个编码类目
        encoding_categories = result.get("encoding_categories", {})
        if not encoding_categories:
            errors.append("未找到任何编码类目数据")
        
        # 检查必填类目
        required_categories = ["scene_setting", "theme_type"]
        for required in required_categories:
            if required not in encoding_categories:
                errors.append(f"缺少必填类目: {self.supported_categories.get(required, required)}")
        
        # 验证每个类目数据的格式
        for category_key, category_data in encoding_categories.items():
            if not isinstance(category_data, dict):
                errors.append(f"类目 {category_key} 数据格式错误")
                continue
            
            if "option" not in category_data:
                errors.append(f"类目 {category_key} 缺少选项值")
            
            if "confidence" not in category_data:
                errors.append(f"类目 {category_key} 缺少置信度")
            
        return len(errors) == 0, errors
    
    def enhance_result(self, result: Dict[str, Any]) -> Dict[str, Any]:
        """
        增强解析结果，添加额外的分析和建议
        
        Args:
            result: 解析后的结果
            
        Returns:
            Dict[str, Any]: 增强后的结果
        """
        # 添加解析统计信息
        encoding_categories = result.get("encoding_categories", {})
        
        # 计算各类目的统计
        result["analysis_summary"] = {
            "total_categories": len(encoding_categories),
            "confident_categories_count": sum(1 for cat in encoding_categories.values() 
                                             if cat.get("confidence", 0) >= 70),
            "low_confidence_categories_count": sum(1 for cat in encoding_categories.values() 
                                                  if cat.get("confidence", 0) < 70),
            "missing_categories_count": sum(1 for cat_key in self.supported_categories 
                                           if cat_key not in encoding_categories),
            "recommendation": self._generate_recommendation(result)
        }
        
        return result
    
    def _generate_recommendation(self, result: Dict[str, Any]) -> str:
        """
        生成分析建议
        
        Args:
            result: 解析后的结果
            
        Returns:
            str: 建议文本
        """
        overall_confidence = result.get("overall_confidence", 0)
        fields_to_supplement = result.get("fields_to_supplement", [])
        
        if overall_confidence >= 80:
            return "分析结果整体置信度高，可直接使用"
        elif overall_confidence >= 60:
            if fields_to_supplement:
                return f"整体置信度适中，建议补充分析以下字段: {', '.join(fields_to_supplement)}"
            else:
                return "整体置信度适中，分析结果可接受"
        else:
            return "整体置信度较低，建议对所有字段进行补充分析"


# 测试代码
if __name__ == "__main__":
    # 配置日志
    logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    
    # 创建解析器实例
    parser = VisionResultParser()
    
    # 测试JSON格式响应
    test_json_response = {
        "success": True,
        "content": "{\"scene_setting\":{\"option\":\"校园场景\",\"confidence\":90},\"audio_material\":{\"option\":\"博主原声\",\"confidence\":85},\"theme_type\":{\"option\":\"学业分享\",\"confidence\":80}}"
    }
    
    # 测试文本格式响应
    test_text_response = {
        "success": True,
        "content": "# 视频分析结果\n场景设定：校园场景 (置信度: 90%)\n声音素材：博主原声 (置信度: 85%)\n主题类型：学业分享 (置信度: 80%)"
    }
    
    # 测试JSON代码块响应
    test_code_block_response = {
        "success": True,
        "content": "分析完成，结果如下：\n```json\n{\"scene_setting\":{\"option\":\"校园场景\",\"confidence\":90},\"audio_material\":{\"option\":\"博主原声\",\"confidence\":85}}\n```"
    }
    
    # 测试解析
    print("测试JSON格式响应解析：")
    result1 = parser.parse_result(test_json_response, "test_video_001")
    print(json.dumps(result1, ensure_ascii=False, indent=2))
    print("\n验证结果：")
    is_valid, errors = parser.validate_result(result1)
    print(f"是否有效: {is_valid}")
    if errors:
        print(f"错误: {errors}")
    
    print("\n" + "="*50 + "\n")
    
    print("测试文本格式响应解析：")
    result2 = parser.parse_result(test_text_response, "test_video_002")
    print(json.dumps(result2, ensure_ascii=False, indent=2))
    
    print("\n" + "="*50 + "\n")
    
    print("测试JSON代码块响应解析：")
    result3 = parser.parse_result(test_code_block_response, "test_video_003")
    print(json.dumps(result3, ensure_ascii=False, indent=2))
    
    print("\n视觉分析结果解析器初始化成功!")